package com.trusfort.redis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.exceptions.JedisException;

import java.util.HashSet;

import org.apache.commons.lang.StringUtils;

/**
 * 首先是不能每次都new一个JedisPool 如何判断连接失败？并且重连。
 */
public class RedisConnectionPool {

	private static RedisConnectionPool instance;
	private JedisPool jedispool;

	// common
	private int timeout = 5000;
	private String passwd;
	private JedisPoolConfig config = new JedisPoolConfig();

	// use one redis
	private String host = "192.168.1.170";
	private int port = 6385;

	private static Object syncObj = new Object();

	/*
	 * 获取RedisConnectionPool实例入口
	 */
	private RedisConnectionPool() {
		init();
	}
	
    private RedisConnectionPool(String host, int port,String passwd) {
        this.host = host;
        this.port = port;
        this.passwd = passwd;
        init();
    }

	// 维护单例类，防止并发时出现多个实例存在的情况。
	public static RedisConnectionPool getInstance() {
		synchronized (syncObj) {
			if (instance == null) {
				instance = new RedisConnectionPool();
			}
		}
		return instance;
	}
	
	   // 获取带自定义配置的实例
    public static RedisConnectionPool getInstance(String host, int port,String passwd) {
        synchronized (syncObj) {
            if (instance == null) {
                instance = new RedisConnectionPool(host, port,passwd);
            } else if (!instance.host.equals(host) || instance.port != port) {
                // 如果配置不同，销毁旧实例创建新实例
                instance.destroy();
                instance = new RedisConnectionPool(host, port,passwd);
            }
        }
        return instance;
    }

	private static void clearInstance() {
		synchronized (syncObj) {
			instance = null;
		}
	}
	
	private static void init2(String hostAndPort) {
		
	}

	private void init() {
		int maxIdle;
		int minIdle;
		int maxActive;
		int maxWait;
		// common
//        timeout = ConfigUtil.getInt("time_out");
//        maxActive = ConfigUtil.getInt("max_active");
//        maxIdle = ConfigUtil.getInt("max_idle");
//        minIdle = ConfigUtil.getInt("min_idle",0);
//        maxWait = ConfigUtil.getInt("max_wait");
//        passwd = ConfigUtil.getString("auth_pwd");

//        boolean testOnBorrow = ConfigUtil.getBoolean("test_on_borrow",true);
//        boolean testWhileIdle = ConfigUtil.getBoolean("test_while_idle",true);

//        //one redis config
//        host = ConfigUtil.getString("redis_host");
//        port = ConfigUtil.getInt("redis_port");

		// here is pool config
//		config.setMaxTotal(maxActive);
//		config.setMaxIdle(maxIdle);
//		config.setMaxWaitMillis(maxWait);
//		config.setMinIdle(minIdle);
//		config.setTestOnBorrow(testOnBorrow);
//		config.setTestWhileIdle(testWhileIdle);

//        log.info("redis init...");
		if (host == null || port == 0 || timeout == 0) {
//            log.error(
//                    "***************Redis Initialization Parameter Could't be null or zero!!!***********");
//            log.error("Host:{}, port:{} timeout:{}", host, port, timeout);
			clearInstance();
			return;
		}
		loadOrReload();
	}

	private void assureNullPasswd() {
		if (passwd == null || passwd.length() == 0)
			passwd = null;
	}

	private void destroyThisJedisPool() {
		if (jedispool != null) {
			jedispool.destroy();
			jedispool = null;
		}
	}

	/**
	 * @author
	 * @description:尝试连接redis服务器，若尝试成功，则保留初始化的连接池；若不成功则销毁。
	 */
	private synchronized void loadOrReload() {
		assureNullPasswd();

//        try {
//            if (StringUtils.isNotEmpty(passwd) ) {
//                passwd = Algorithm.getDecryptedPwd(passwd);
//            }
//        } catch (Exception e) {
//            log.error("Redis密码解密失败{}",e.getMessage(),e);
//        }

		// init one jedis pool
//            log.info("connect redis - {} - {} - {} ", host, port, timeout);
		jedispool = new JedisPool(config, host, port, timeout, passwd);

		validate();
	}

	private void validate() {
		Jedis j = null;
		try {
			j = getJedis();
			j.set("checkout", "need response");
			j.close();

		} catch (Exception e) {
//            log.error("Connect Redis Server:{}:{} failed.{}", host, port, e);
			if (j != null)
				j.close();
			destroy();
			clearInstance();
		}
	}

	/**
	 * 获取Jedis实例
	 *
	 * @return
	 */
	private Jedis getJedis() throws RedisException {
		try {
			if (jedispool == null)
				loadOrReload();
			return jedispool.getResource();
		} catch (Exception e) {
//            log.error("连接redis异常：-[{}]",e.getMessage());
			throw new RedisException(e);
		}

	}

	/**
	 * 获取Jedis实例(指定数据库索引)
	 *
	 * @param dbIndex
	 * @return
	 * @throws Exception
	 */
	public Jedis getJedis(Integer dbIndex) throws RedisException {
		 

		Jedis jedis = getJedis();
		jedis.select(dbIndex);
//        if (StringUtils.isNotEmpty(passwd))
//            jedis.auth(passwd);

		return jedis;

	}

	/**
	 * 返还到连接池
	 */
	public void returnResource(Jedis jedis) {

		if (jedis != null) {
			jedis.close();
		}

	}

	/**
	 * 销毁Redis连接池
	 */
	public synchronized void destroy() {
//        log.debug("-------Redis连接池撤销-------");
		try {
			if (jedispool != null) {
				jedispool.destroy();
				jedispool = null;
			}
		} catch (JedisException je) {
//            log.error("撤销Redis连接池错误", je);
		}
	}

}
